<!DOCTYPE html>



  


<html class="theme-next mist use-motion" lang="zh-Hans">
<head><meta name="generator" content="Hexo 3.9.0">
  <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="theme-color" content="#222">









<meta http-equiv="Cache-Control" content="no-transform">
<meta http-equiv="Cache-Control" content="no-siteapp">
















  
  
  <link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css">







<link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css">

<link href="/css/main.css?v=5.1.4" rel="stylesheet" type="text/css">


  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png?v=5.1.4">


  <link rel="mask-icon" href="/images/logo.svg?v=5.1.4" color="#222">





  <meta name="keywords" content="反射,JVM,转载,">










<meta name="description" content="【转载】深入理解Java类型信息(Class对象)与反射机制-原文连接">
<meta name="keywords" content="反射,JVM,转载">
<meta property="og:type" content="article">
<meta property="og:title" content="Java-深入理解Java类型（Class对象）与反射机制">
<meta property="og:url" content="https://briarbear.github.io/2018/07/09/Java-深入理解Java类型（Class对象）与反射机制/index.html">
<meta property="og:site_name" content="briarbear | 熊大">
<meta property="og:description" content="【转载】深入理解Java类型信息(Class对象)与反射机制-原文连接">
<meta property="og:locale" content="zh-Hans">
<meta property="og:image" content="http://cdn.briarbear.cn/201807091124_291.png">
<meta property="og:image" content="http://cdn.briarbear.cn/201807091214_344.png">
<meta property="og:updated_time" content="2019-08-25T08:28:49.576Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Java-深入理解Java类型（Class对象）与反射机制">
<meta name="twitter:description" content="【转载】深入理解Java类型信息(Class对象)与反射机制-原文连接">
<meta name="twitter:image" content="http://cdn.briarbear.cn/201807091124_291.png">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/',
    scheme: 'Mist',
    version: '5.1.4',
    sidebar: {"position":"right","display":"hide","offset":12,"b2t":false,"scrollpercent":false,"onmobile":false},
    fancybox: true,
    tabs: true,
    motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
    duoshuo: {
      userId: '0',
      author: '博主'
    },
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="https://briarbear.github.io/2018/07/09/Java-深入理解Java类型（Class对象）与反射机制/">





  <title>Java-深入理解Java类型（Class对象）与反射机制 | briarbear | 熊大</title>
  








</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans">

  
  
    
  

  <div class="container sidebar-position-right page-post-detail">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/" class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">briarbear | 熊大</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
      
        <p class="site-subtitle">/- 记录技术成长点滴 -/</p>
      
  </div>

  <div class="site-nav-toggle">
    <button>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br>
            
            首页
          </a>
        </li>
      
        
        <li class="menu-item menu-item-about">
          <a href="/about/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-user"></i> <br>
            
            关于
          </a>
        </li>
      
        
        <li class="menu-item menu-item-tags">
          <a href="/tags/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-tags"></i> <br>
            
            标签
          </a>
        </li>
      
        
        <li class="menu-item menu-item-categories">
          <a href="/categories/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-th"></i> <br>
            
            分类
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/archives/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br>
            
            归档
          </a>
        </li>
      

      
        <li class="menu-item menu-item-search">
          
            <a href="javascript:;" class="popup-trigger">
          
            
              <i class="menu-item-icon fa fa-search fa-fw"></i> <br>
            
            搜索
          </a>
        </li>
      
    </ul>
  

  
    <div class="site-search">
      
  <div class="popup search-popup local-search-popup">
  <div class="local-search-header clearfix">
    <span class="search-icon">
      <i class="fa fa-search"></i>
    </span>
    <span class="popup-btn-close">
      <i class="fa fa-times-circle"></i>
    </span>
    <div class="local-search-input-wrapper">
      <input autocomplete="off" placeholder="搜索..." spellcheck="false" type="text" id="local-search-input">
    </div>
  </div>
  <div id="local-search-result"></div>
</div>



    </div>
  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://briarbear.github.io/2018/07/09/Java-深入理解Java类型（Class对象）与反射机制/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="Briar·bear">
      <meta itemprop="description" content>
      <meta itemprop="image" content="/images/photo.png">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="briarbear | 熊大">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">Java-深入理解Java类型（Class对象）与反射机制</h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2018-07-09T16:30:42+08:00">
                2018-07-09
              </time>
            

            

            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">分类于</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/Java/" itemprop="url" rel="index">
                    <span itemprop="name">Java</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
              <span class="post-comments-count">
                <span class="post-meta-divider">|</span>
                <span class="post-meta-item-icon">
                  <i class="fa fa-comment-o"></i>
                </span>
                <a href="/2018/07/09/Java-深入理解Java类型（Class对象）与反射机制/#comments" itemprop="discussionUrl">
                  <span class="post-comments-count gitment-comments-count" data-xid="/2018/07/09/Java-深入理解Java类型（Class对象）与反射机制/" itemprop="commentsCount"></span>
                </a>
              </span>
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        <blockquote>
<p>【转载】<a href="https://blog.csdn.net/javazejian/article/details/70768369" target="_blank" rel="noopener">深入理解Java类型信息(Class对象)与反射机制-原文连接</a></p>
</blockquote>
<a id="more"></a>

<h2 id="1-深入理解Class对象"><a href="#1-深入理解Class对象" class="headerlink" title="1. 深入理解Class对象"></a>1. 深入理解Class对象</h2><h3 id="1-1-RRTI的概念以及Class对象引用"><a href="#1-1-RRTI的概念以及Class对象引用" class="headerlink" title="1.1 RRTI的概念以及Class对象引用"></a>1.1 RRTI的概念以及Class对象引用</h3><p>认识<code>Class</code>对象之前，先来了解一个概念，RTTI（Run-Time Type Identification）运行时类型识别，对于这个词一直是 C++ 中的概念，至于Java中出现RRTI的说法则是源于《Thinking in Java》一书，其作用是在运行时识别一个对象的类型和类的信息，这里分两种：传统的”RRTI”,它假定我们在编译期已知道了所有类型(在没有反射机制创建和使用类对象时，一般都是编译期已确定其类型，如new对象时该类必须已定义好)，另外一种是反射机制，它允许我们在运行时发现和使用类型的信息。在Java中用来表示运行时类型信息的对应类就是<code>Class</code>类，<code>Class</code>类也是一个实实在在的类，存在于<code>JDK</code>的<code>java.lang</code>包中，其部分源码如下：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">final</span> <span class="class"><span class="keyword">class</span> <span class="title">Class</span>&lt;<span class="title">T</span>&gt; <span class="keyword">implements</span> <span class="title">java</span>.<span class="title">io</span>.<span class="title">Serializable</span>,<span class="title">GenericDeclaration</span>,<span class="title">Type</span>, <span class="title">AnnotatedElement</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> ANNOTATION= <span class="number">0x00002000</span>;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> ENUM      = <span class="number">0x00004000</span>;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> SYNTHETIC = <span class="number">0x00001000</span>;</span><br><span class="line"> </span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">native</span> <span class="keyword">void</span> <span class="title">registerNatives</span><span class="params">()</span></span>;</span><br><span class="line">    <span class="keyword">static</span> &#123;</span><br><span class="line">        registerNatives();</span><br><span class="line">    &#125;</span><br><span class="line"> </span><br><span class="line">    <span class="comment">/*</span></span><br><span class="line"><span class="comment">     * Private constructor. Only the Java Virtual Machine creates Class objects.（私有构造，只能由JVM创建该类）</span></span><br><span class="line"><span class="comment">     * This constructor is not used and prevents the default constructor being</span></span><br><span class="line"><span class="comment">     * generated.</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="title">Class</span><span class="params">(ClassLoader loader)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// Initialize final field for classLoader.  The initialization value of non-null</span></span><br><span class="line">        <span class="comment">// prevents future JIT optimizations from assuming this final field is null.</span></span><br><span class="line">        classLoader = loader;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>

<p><code>Class</code>类被创建后的对象就是<code>Class</code>对象，注意，<code>Class</code>对象表示的是自己手动编写类的类型信息，比如创建一个<code>Shapes</code>类，那么，JVM就会创建一个<code>Shapes</code>对应<code>Class</code>类的<code>Class</code>对象，该<code>Class</code>对象保存了<code>Shapes</code>类相关的类型信息。实际上在Java中每个类都有一个<code>Class</code>对象，每当我们编写并且编译一个新创建的类就会产生一个对应<code>Class</code>对象并且这个<code>Class</code>对象会被保存在同名.class文件里(编译后的字节码文件保存的就是Class对象)，那为什么需要这样一个<code>Class</code>对象呢？是这样的，当我们new一个新对象或者引用静态成员变量时，Java虚拟机(JVM)中的类加载器子系统会将对应<code>Class</code>对象加载到<code>JVM</code>中，然后JVM再根据这个类型信息相关的<code>Class</code>对象创建我们需要实例对象或者提供静态变量的引用值。需要特别注意的是，手动编写的每个<code>class</code>类，无论创建多少个实例对象，在JVM中都只有一个<code>Class</code>对象，即在内存中每个类有且只有一个相对应的<code>Class</code>对象，挺拗口，通过下图理解（内存中的简易现象图）：</p>
<p><img src="http://cdn.briarbear.cn/201807091124_291.png" alt></p>
<h3 id="1-2-总结信息"><a href="#1-2-总结信息" class="headerlink" title="1.2 总结信息"></a>1.2 总结信息</h3><p>到这我们也就可以得出以下几点信息：</p>
<ul>
<li><code>Class</code>类也是类的一种，与class关键字是不一样的。</li>
<li>手动编写的类被编译后会产生一个<code>Class</code>对象，其表示的是创建的类的类型信息，而且这个<code>Class</code>对象保存在同名.class的文件中(字节码文件)，比如创建一个<code>Shapes</code>类，编译<code>Shapes</code>类后就会创建其包含<code>Shapes</code>类相关类型信息的<code>Class</code>对象，并保存在Shapes.class字节码文件中。</li>
<li>每个通过关键字class标识的类，在内存中有且只有一个与之对应的<code>Class</code>对象来描述其类型信息，无论创建多少个实例对象，其依据的都是用一个<code>Class</code>对象。</li>
<li><code>Class</code>类只存私有构造函数，因此对应<code>Class</code>对象只能有JVM创建和加载</li>
<li><code>Class</code>类的对象作用是运行时提供或获得某个对象的类型信息，这点对于反射技术很重要(关于反射稍后分析)。</li>
</ul>
<hr>
<h2 id="2-Class对象的加载及其获取方法"><a href="#2-Class对象的加载及其获取方法" class="headerlink" title="2. Class对象的加载及其获取方法"></a>2. Class对象的加载及其获取方法</h2><h3 id="2-1-Class对象的加载"><a href="#2-1-Class对象的加载" class="headerlink" title="2.1 Class对象的加载"></a>2.1 Class对象的加载</h3><p>前面我们已提到过，Class对象是由JVM加载的，那么其加载时机是？实际上所有的类都是在对其第一次使用时动态加载到JVM中的，当程序创建第一个对类的静态成员引用时，就会加载这个被使用的类(实际上加载的就是这个类的字节码文件)，注意，使用new操作符创建类的新实例对象也会被当作对类的静态成员的引用(构造函数也是类的静态方法)，由此看来Java程序在它们开始运行之前并非被完全加载到内存的，其各个部分是按需加载，所以在使用该类时，类加载器首先会检查这个类的Class对象是否已被加载(类的实例对象创建时依据Class对象中类型信息完成的)，如果还没有加载，默认的类加载器就会先根据类名查找.class文件(编译后Class对象被保存在同名的.class文件中)，在这个类的字节码文件被加载时，它们必须接受相关验证，以确保其没有被破坏并且不包含不良Java代码(这是java的安全机制检测)，完全没有问题后就会被动态加载到内存中，此时相当于Class对象也就被载入内存了(毕竟.class字节码文件保存的就是Class对象)，同时也就可以被用来创建这个类的所有实例对象。下面通过一个简单例子来说明Class对象被加载的时机问题（例子引用自Thinking in Java）：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Candy</span> </span>&#123;</span><br><span class="line">  <span class="keyword">static</span> &#123;   System.out.println(<span class="string">"Loading Candy"</span>); &#125;</span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Gum</span> </span>&#123;</span><br><span class="line">  <span class="keyword">static</span> &#123;   System.out.println(<span class="string">"Loading Gum"</span>); &#125;</span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Cookie</span> </span>&#123;</span><br><span class="line">  <span class="keyword">static</span> &#123;   System.out.println(<span class="string">"Loading Cookie"</span>); &#125;</span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">SweetShop</span> </span>&#123;</span><br><span class="line">  <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">print</span><span class="params">(Object obj)</span> </span>&#123;</span><br><span class="line">    System.out.println(obj);</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123; </span><br><span class="line">    print(<span class="string">"inside main"</span>);</span><br><span class="line">    <span class="keyword">new</span> Candy();</span><br><span class="line">    print(<span class="string">"After creating Candy"</span>);</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">      Class.forName(<span class="string">"com.zejian.Gum"</span>);</span><br><span class="line">    &#125; <span class="keyword">catch</span>(ClassNotFoundException e) &#123;</span><br><span class="line">      print(<span class="string">"Couldn't find Gum"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    print(<span class="string">"After Class.forName(\"com.zejian.Gum\")"</span>);</span><br><span class="line">    <span class="keyword">new</span> Cookie();</span><br><span class="line">    print(<span class="string">"After creating Cookie"</span>);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>在上述代码中,每个类Candy、Gum、Cookie都存在一个static语句，这个语句会在类第一次被加载时执行，这个语句的作用就是告诉我们该类在什么时候被加载，执行结果 :</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">inside main</span><br><span class="line">Loading Candy</span><br><span class="line">After creating Candy</span><br><span class="line">Loading Gum</span><br><span class="line">After Class.forName("com.zejian.Gum")</span><br><span class="line">Loading Cookie</span><br><span class="line">After creating Cookie</span><br><span class="line"> </span><br><span class="line">Process finished with exit code 0</span><br></pre></td></tr></table></figure>

<p>从结果来看，new一个Candy对象和Cookie对象，构造函数将被调用，属于静态方法的引用，Candy类的Class对象和Cookie的Class对象肯定会被加载，毕竟Candy实例对象的创建依据其Class对象。比较有意思的是</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Class.forName(<span class="string">"reflect.Gum"</span>);</span><br></pre></td></tr></table></figure>

<p>其中<code>forName</code>方法是<code>Class</code>类的一个static成员方法，记住所有的Class对象都源于这个Class类，因此Class类中定义的方法将适应所有Class对象。这里通过<code>forName</code>方法，我们可以获取到Gum类对应的Class对象引用。从打印结果来看，调用<code>forName</code>方法将会导致Gum类被加载(前提是Gum类从来没有被加载过)</p>
<h3 id="2-2-Class-forName方法"><a href="#2-2-Class-forName方法" class="headerlink" title="2.2 Class.forName方法"></a>2.2 Class.forName方法</h3><p>通过上述的案例，我们也就知道<code>Class.forName()</code>方法的调用将会返回一个对应类的Class对象，因此如果我们想获取一个类的运行时类型信息并加以使用时，可以调用<code>Class.forName()</code>方法获取Class对象的引用，这样做的好处是无需通过持有该类的实例对象引用而去获取Class对象，如下的第2种方式是通过一个实例对象获取一个类的Class对象，其中的<code>getClass()</code>是从顶级类Object继承而来的，它将返回表示该对象的实际类型的Class对象引用。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line"> </span><br><span class="line">    <span class="keyword">try</span>&#123;</span><br><span class="line">      <span class="comment">//通过Class.forName获取Gum类的Class对象</span></span><br><span class="line">      Class clazz=Class.forName(<span class="string">"com.zejian.Gum"</span>);</span><br><span class="line">      System.out.println(<span class="string">"forName=clazz:"</span>+clazz.getName());</span><br><span class="line">    &#125;<span class="keyword">catch</span> (ClassNotFoundException e)&#123;</span><br><span class="line">      e.printStackTrace();</span><br><span class="line">    &#125;</span><br><span class="line"> </span><br><span class="line">    <span class="comment">//通过实例对象获取Gum的Class对象</span></span><br><span class="line">    Gum gum = <span class="keyword">new</span> Gum();</span><br><span class="line">    Class clazz2=gum.getClass();</span><br><span class="line">    System.out.println(<span class="string">"new=clazz2:"</span>+clazz2.getName());</span><br><span class="line"> </span><br><span class="line">  &#125;</span><br></pre></td></tr></table></figure>

<p>注意调用<code>forName</code>方法时需要捕获一个名称为<code>ClassNotFoundException</code>的异常，因为<code>forName</code>方法在编译器是无法检测到其传递的字符串对应的类是否存在的，只能在程序运行时进行检查，如果不存在就会抛出<code>ClassNotFoundException</code>异常。</p>
<h3 id="2-3-Class字面常量"><a href="#2-3-Class字面常量" class="headerlink" title="2.3 Class字面常量"></a>2.3 Class字面常量</h3><p>在Java中存在另一种方式来生成Class对象的引用，它就是Class字面常量，如下：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//字面常量的方式获取Class对象</span></span><br><span class="line">Class clazz = Gum.class;</span><br></pre></td></tr></table></figure>

<p>这种方式相对前面两种方法更加简单，更安全。因为它在编译器就会受到编译器的检查同时由于无需调用forName方法效率也会更高，因为通过字面量的方法获取Class对象的引用不会自动初始化该类。更加有趣的是字面常量的获取Class对象引用方式不仅可以应用于普通的类，也可以应用用接口，数组以及基本数据类型，这点在反射技术应用传递参数时很有帮助，关于反射技术稍后会分析，由于基本数据类型还有对应的基本包装类型，其包装类型有一个标准字段TYPE，而这个TYPE就是一个引用，指向基本数据类型的Class对象，其等价转换如下，一般情况下更倾向使用.class的形式，这样可以保持与普通类的形式统一。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">boolean</span>.class = Boolean.TYPE;</span><br><span class="line"><span class="keyword">char</span>.class = Character.TYPE;</span><br><span class="line"><span class="keyword">byte</span>.class = Byte.TYPE;</span><br><span class="line"><span class="keyword">short</span>.class = Short.TYPE;</span><br><span class="line"><span class="keyword">int</span>.class = Integer.TYPE;</span><br><span class="line"><span class="keyword">long</span>.class = Long.TYPE;</span><br><span class="line"><span class="keyword">float</span>.class = Float.TYPE;</span><br><span class="line"><span class="keyword">double</span>.class = Double.TYPE;</span><br><span class="line"><span class="keyword">void</span>.class = Void.TYPE;</span><br></pre></td></tr></table></figure>

<p>前面提到过，使用字面常量的方式获取Class对象的引用不会触发类的初始化，这里我们可能需要简单了解一下类加载的过程，如下：</p>
<p><img src="http://cdn.briarbear.cn/201807091214_344.png" alt></p>
<ul>
<li><p><strong>加载</strong>：类加载过程的第一个阶段：通过一个类的完全限定查找此类字节码文件，并利用字节码文件创建一个</p>
<p>Class对象</p>
</li>
<li><p><strong>连接</strong>：验证字节码的安全性和完整性，准备阶段正式为静态域分配存储空间，注意此时只是分配静态成员变量的存储空间，不包含实例成员变量，如果必要的话，解析这个类创建的对其他类的所有引用</p>
</li>
<li><p><strong>初始化</strong> :类加载最后阶段，若该类具有超类，则对其进行初始化，执行静态初始化器和静态初始化成员变量</p>
</li>
</ul>
<p>由此可知，我们获取字面常量的<code>Class</code>引用时，触发的应该是加载阶段，因为在这个阶段<code>Class</code>对象已创建完成，获取其引用并不困难，而无需触发类的最后阶段初始化。下面通过小例子来验证这个过程:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Initable</span></span>&#123;</span><br><span class="line">    <span class="comment">//编译器静态变量</span></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> staticFianl = <span class="number">47</span>;</span><br><span class="line">    <span class="comment">//非编译期静态常量</span></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> staticFinal2  = ClassInitialization.rand.nextInt(<span class="number">1000</span>);</span><br><span class="line"> </span><br><span class="line">    <span class="keyword">static</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">"Initializing Initable"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Initable2</span></span>&#123;</span><br><span class="line">    <span class="comment">//静态成员变量</span></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">int</span> staicNonFinal = <span class="number">147</span>;</span><br><span class="line">    <span class="keyword">static</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">"Initializing Initable2"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Initable3</span></span>&#123;</span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">int</span> staticNonFinal = <span class="number">74</span>;</span><br><span class="line">    <span class="keyword">static</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">"Initializing Initable3"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ClassInitialization</span> </span>&#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> Random rand = <span class="keyword">new</span> Random(<span class="number">47</span>);</span><br><span class="line"> </span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> ClassNotFoundException </span>&#123;</span><br><span class="line">        <span class="comment">//字面常量获取方式获取Class对象</span></span><br><span class="line">        Class initable =  Initable.class;</span><br><span class="line">        System.out.println(<span class="string">"After createing Initable ref"</span>);</span><br><span class="line"> </span><br><span class="line">        <span class="comment">//不触发类初始化</span></span><br><span class="line">        System.out.println(<span class="string">"1:"</span>+Initable.staticFianl);</span><br><span class="line"> </span><br><span class="line">        <span class="comment">//会触发类初始化</span></span><br><span class="line">        System.out.println(<span class="string">"1:"</span>+Initable.staticFinal2);</span><br><span class="line"> </span><br><span class="line">        <span class="comment">//会触发类的初始化</span></span><br><span class="line">        System.out.println(<span class="string">"2:"</span>+Initable2.staicNonFinal);</span><br><span class="line"> </span><br><span class="line">        <span class="comment">//forName方法获取Class对象</span></span><br><span class="line">        Class initable3 = Class.forName(<span class="string">"reflect.csdn.Initable3"</span>);</span><br><span class="line">        System.out.println(<span class="string">"After createing Initable3 ref"</span>);</span><br><span class="line">        System.out.println(<span class="string">"3:"</span>+Initable3.staticNonFinal);</span><br><span class="line"> </span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>运行结果：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">After createing Initable ref</span><br><span class="line">1:47</span><br><span class="line">Initializing Initable</span><br><span class="line">1:258</span><br><span class="line">Initializing Initable2</span><br><span class="line">2:147</span><br><span class="line">Initializing Initable3</span><br><span class="line">After createing Initable3 ref</span><br><span class="line">3:74</span><br><span class="line"> </span><br><span class="line">Process finished with exit code 0</span><br></pre></td></tr></table></figure>

<p>从输出结果来看，可以发现，通过字面常量获取方式获取<code>Initable</code>类的<code>Class</code>对象并没有触发<code>Initable</code>类的初始化，这点也验证了前面的分析，同时发现调用<code>Initable.staticFinal</code>变量时也没有触发初始化，这是因为<code>staticFinal</code>属于编译期静态常量，在编译阶段通过常量传播优化的方式将<code>Initable</code>类的常量<code>staticFinal</code>存储到了一个称为<code>NotInitialization</code>类的常量池中，在以后对<code>Initable</code>类常量<code>staticFinal</code>的引用实际都转化为对<code>NotInitialization</code>类对自身常量池的引用，所以在编译期后，对编译期常量的引用都将在<code>NotInitialization</code>类的常量池获取，这也就是引用编译期静态常量不会触发<code>Initable</code>类初始化的重要原因。但在之后调用了<code>Initable.staticFinal2</code>变量后就触发了<code>Initable</code>类的初始化，注意<code>staticFinal2</code>虽然被<code>static</code>和<code>final</code>修饰，但其值在编译期并不能确定，因此<code>staticFinal2</code>并不是编译期常量，使用该变量必须先初始化<code>Initable</code>类。<code>Initable2</code>和<code>Initable3</code>类中都是静态成员变量并非编译期常量，引用都会触发初始化。至于<code>forName</code>方法获取<code>Class</code>对象，肯定会触发初始化，这点在前面已分析过。到这几种获取<code>Class</code>对象的方式也都分析完，ok~,到此这里可以得出小结论：</p>
<ul>
<li>获取Class对象引用的方式3种，通过继承自<code>Object</code>类的<code>getClass</code>方法，<code>Class</code>类的静态方法<code>forName</code>以及字面常量的方式<code>.class</code>。</li>
<li>其中实例类的<code>getClass</code>方法和Class类的静态方法<code>forName</code>都将会触发类的初始化阶段，而字面常量获取<code>Class</code>对象的方式则不会触发初始化。</li>
<li>初始化是类加载的最后一个阶段，也就是说完成这个阶段后类也就加载到内存中(<code>Class</code>对象在加载阶段已被创建)，此时可以对类进行各种必要的操作了（如<code>new</code>对象，调用静态成员等），注意在这个阶段，才真正开始执行类中定义的Java程序代码或者字节码</li>
</ul>
<p><em>关于类加载的初始化阶段，在虚拟机规范严格规定了有且只有5种场景必须对类进行初始化</em></p>
<ul>
<li>使用new关键字实例化对象时、读取或者设置一个类的静态字段(不包含编译期常量)以及调用静态方法的时候，必须触发类加载的初始化过程(类加载过程最终阶段)</li>
<li>使用反射包(<code>java.lang.reflect</code>)的方法对类进行反射调用时，如果类还没有被初始化，则需先进行初始化，这点对反射很重要。</li>
<li>当初始化一个类的时候，如果其父类还没进行初始化则需先触发其父类的初始化</li>
<li>当Java虚拟机启动时，用户需要指定一个要执行的主类(包含main方法的类)，虚拟机会先初始化这个主类</li>
<li>当使用JDK 1.7 的动态语言支持时，如果一个<code>java.lang.invoke.MethodHandle</code> 实例最后解析结果为<code>REF_getStatic</code>、<code>REF_putStatic</code>、<code>REF_invokeStatic</code>的方法句柄，并且这个方法句柄对应类没有初始化时，必须触发其初始化(这点看不懂就算了，这是1.7的新增的动态语言支持，其关键特征是它的类型检查的主体过程是在运行期而不是编译期进行的，这是一个比较大点的话题，这里暂且打住)</li>
</ul>
<h3 id="2-4-理解泛化的Class对象引用"><a href="#2-4-理解泛化的Class对象引用" class="headerlink" title="2.4 理解泛化的Class对象引用"></a>2.4 理解泛化的Class对象引用</h3><p>由于Class的引用总数指向某个类的Class对象，利用Class对象可以创建实例类，这也就足以说明Class对象的引用指向的对象确切的类型。在Java SE5引入泛型后，使用我们可以利用泛型来表示Class对象更具体的类型，即使在运行期间会被擦除，但编译期足以确保我们使用正确的对象类型。如下:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* Created by zejian on 2017/4/30.</span></span><br><span class="line"><span class="comment">* Blog : http://blog.csdn.net/javazejian [原文地址,请尊重原创]</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ClazzDemo</span> </span>&#123;</span><br><span class="line"> </span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span></span>&#123;</span><br><span class="line">        <span class="comment">//没有泛型</span></span><br><span class="line">        Class intClass = <span class="keyword">int</span>.class;</span><br><span class="line"> </span><br><span class="line">        <span class="comment">//带泛型的Class对象</span></span><br><span class="line">        Class&lt;Integer&gt; integerClass = <span class="keyword">int</span>.class;</span><br><span class="line"> </span><br><span class="line">        integerClass = Integer.class;</span><br><span class="line"> </span><br><span class="line">        <span class="comment">//没有泛型的约束,可以随意赋值</span></span><br><span class="line">        intClass= <span class="keyword">double</span>.class;</span><br><span class="line"> </span><br><span class="line">        <span class="comment">//编译期错误,无法编译通过</span></span><br><span class="line">        <span class="comment">//integerClass = double.class</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>从代码可以看出，声明普通的Class对象，在编译器并不会检查Class对象的确切类型是否符合要求，如果存在错误只有在运行时才得以暴露出来。但是通过泛型声明指明类型的Class对象，编译器在编译期将对带泛型的类进行额外的类型检查，确保在编译期就能保证类型的正确性，实际上<code>Integer.class</code>就是一个<code>Class&lt;Integer&gt;</code>类的对象。面对下述语句，确实可能令人困惑，但该语句确实是无法编译通过的。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//编译无法通过</span></span><br><span class="line">Class&lt;Number&gt; numberClass=Integer.class;</span><br></pre></td></tr></table></figure>

<p>我们或许会想Integer不就是Number的子类吗？然而事实并非这般简单，毕竟Integer的Class对象并非Number的Class对象的子类，前面提到过，所有的Class对象都只来源于Class类，看来事实确实如此。当然我们可以利用通配符“?”来解决问题：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Class&lt;?&gt; intClass = <span class="keyword">int</span>.class;</span><br><span class="line">intClass = <span class="keyword">double</span>.class;</span><br></pre></td></tr></table></figure>

<p>这样的语句并没有什么问题，毕竟通配符指明所有类型都适用，那么为什么不直接使用Class还要使用<code>Class&lt;?&gt;</code>呢？这样做的好处是告诉编译器，我们是确实是采用任意类型的泛型，而非忘记使用泛型约束，因此<code>Class&lt;?&gt;</code>总是优于直接使用Class，至少前者在编译器检查时不会产生警告信息。当然我们还可以使用extends关键字告诉编译器接收某个类型的子类，如解决前面Number与Integer的问题：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//编译通过！</span></span><br><span class="line">Class&lt;? extends Number&gt; clazz = Integer.class;</span><br><span class="line"><span class="comment">//赋予其他类型</span></span><br><span class="line">clazz = <span class="keyword">double</span>.class;</span><br><span class="line">clazz = Number.class;</span><br></pre></td></tr></table></figure>

<p>上述的代码是行得通的，extends关键字的作用是告诉编译器，只要是Number的子类都可以赋值。这点与前面直接使用<code>Class&lt;Number&gt;</code>是不一样的。实际上，应该时刻记住向Class引用添加泛型约束仅仅是为了提供编译期类型的检查从而避免将错误延续到运行时期。</p>
<h3 id="2-5-关于类型转换的问题"><a href="#2-5-关于类型转换的问题" class="headerlink" title="2.5 关于类型转换的问题"></a>2.5 关于类型转换的问题</h3><p>在许多需要强制类型转换的场景，我们更多的做法是直接强制转换类型：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ClassCast</span> </span>&#123;</span><br><span class="line"> </span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">cast</span><span class="params">()</span></span>&#123;</span><br><span class="line"> </span><br><span class="line">     Animal animal= <span class="keyword">new</span> Dog();</span><br><span class="line">     <span class="comment">//强制转换</span></span><br><span class="line">     Dog dog = (Dog) animal;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"><span class="class"><span class="keyword">interface</span> <span class="title">Animal</span></span>&#123; &#125;</span><br><span class="line"> </span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Dog</span> <span class="keyword">implements</span>  <span class="title">Animal</span></span>&#123; &#125;</span><br></pre></td></tr></table></figure>

<p>之所可以强制转换，这得归功于RRTI，要知道在Java中，所有类型转换都是在运行时进行正确性检查的，利用RRTI进行判断类型是否正确从而确保强制转换的完成，如果类型转换失败，将会抛出类型转换异常。除了强制转换外，在Java SE5中新增一种使用Class对象进行类型转换的方式，如下：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Animal animal= <span class="keyword">new</span> Dog();</span><br><span class="line"><span class="comment">//这两句等同于Dog dog = (Dog) animal;</span></span><br><span class="line">Class&lt;Dog&gt; dogType = Dog.class;</span><br><span class="line">Dog dog = dogType.cast(animal)</span><br></pre></td></tr></table></figure>

<p>利用Class对象的cast方法，其参数接收一个参数对象并将其转换为Class引用的类型。这种方式似乎比之前的强制转换更麻烦些，确实如此，而且当类型不能正确转换时，仍然会抛出<code>ClassCastException</code>异常。源码如下</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> T <span class="title">cast</span><span class="params">(Object obj)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (obj != <span class="keyword">null</span> &amp;&amp; !isInstance(obj))</span><br><span class="line">         <span class="keyword">throw</span> <span class="keyword">new</span> ClassCastException(cannotCastMsg(obj));</span><br><span class="line">     <span class="keyword">return</span> (T) obj;</span><br><span class="line">  &#125;</span><br></pre></td></tr></table></figure>

<h3 id="2-5-instanceof-关键字与-isInstance-方法"><a href="#2-5-instanceof-关键字与-isInstance-方法" class="headerlink" title="2.5 instanceof 关键字与 isInstance()方法"></a>2.5 instanceof 关键字与 isInstance()方法</h3><p>关于<code>instanceof</code> 关键字，它返回一个<code>boolean</code>类型的值，意在告诉我们对象是不是某个特定的类型实例。如下，在强制转换前利用<code>instanceof</code>检测<code>obj</code>是不是<code>Animal</code>类型的实例对象，如果返回true再进行类型转换，这样可以避免抛出类型转换的异常(<code>ClassCastException</code>)</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">cast2</span><span class="params">(Object obj)</span></span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(obj <span class="keyword">instanceof</span> Animal)&#123;</span><br><span class="line">          Animal animal= (Animal) obj;</span><br><span class="line">      &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>而<code>isInstance()</code>方法则是Class类中的一个Native方法，也是用于判断对象类型的，看个简单例子：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">cast2</span><span class="params">(Object obj)</span></span>&#123;</span><br><span class="line">        <span class="comment">//instanceof关键字</span></span><br><span class="line">        <span class="keyword">if</span>(obj <span class="keyword">instanceof</span> Animal)&#123;</span><br><span class="line">            Animal animal= (Animal) obj;</span><br><span class="line">        &#125;</span><br><span class="line"> </span><br><span class="line">        <span class="comment">//isInstance方法</span></span><br><span class="line">        <span class="keyword">if</span>(Animal.class.isInstance(obj))&#123;</span><br><span class="line">            Animal animal= (Animal) obj;</span><br><span class="line">        &#125;</span><br><span class="line">  &#125;</span><br></pre></td></tr></table></figure>

<p>事实上<code>instanceOf</code> 与<code>isInstance()</code>方法产生的结果是相同的。对于<code>instanceOf</code>是关键字只被用于对象引用变量，检查左边对象是不是右边类或接口的实例化。如果被测对象是null值，则测试结果总是false。一般形式：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//判断这个对象是不是这种类型</span></span><br><span class="line">obj.<span class="keyword">instanceof</span>(<span class="class"><span class="keyword">class</span>)</span></span><br></pre></td></tr></table></figure>

<p>而<code>isInstance()</code>方法则是Class类的Native方法，其中obj是被测试的对象或者变量，如果obj是调用这个方法的class或接口的实例，则返回true。如果被检测的对象是null或者基本类型，那么返回值是false;一般形式如下</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//判断这个对象能不能被转化为这个类</span></span><br><span class="line"><span class="class"><span class="keyword">class</span>.<span class="title">inInstance</span>(<span class="title">obj</span>)</span></span><br></pre></td></tr></table></figure>

<p>最后这里给出一个简单实例，验证<code>isInstance</code>方法与<code>instanceof</code>等价性：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span> </span>&#123;&#125;</span><br><span class="line"> </span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">B</span> <span class="keyword">extends</span> <span class="title">A</span> </span>&#123;&#125;</span><br><span class="line"> </span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">C</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">static</span> <span class="keyword">void</span> <span class="title">test</span><span class="params">(Object x)</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"Testing x of type "</span> + x.getClass());</span><br><span class="line">        System.out.println(<span class="string">"x instanceof A "</span> + (x <span class="keyword">instanceof</span> A));</span><br><span class="line">        System.out.println(<span class="string">"x instanceof B "</span>+ (x <span class="keyword">instanceof</span> B));</span><br><span class="line">        System.out.println(<span class="string">"A.isInstance(x) "</span>+ A.class.isInstance(x));</span><br><span class="line">        System.out.println(<span class="string">"B.isInstance(x) "</span> +</span><br><span class="line">                B.class.isInstance(x));</span><br><span class="line">        System.out.println(<span class="string">"x.getClass() == A.class "</span> +</span><br><span class="line">                (x.getClass() == A.class));</span><br><span class="line">        System.out.println(<span class="string">"x.getClass() == B.class "</span> +</span><br><span class="line">                (x.getClass() == B.class));</span><br><span class="line">        System.out.println(<span class="string">"x.getClass().equals(A.class)) "</span>+</span><br><span class="line">                (x.getClass().equals(A.class)));</span><br><span class="line">        System.out.println(<span class="string">"x.getClass().equals(B.class)) "</span> +</span><br><span class="line">                (x.getClass().equals(B.class)));</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        test(<span class="keyword">new</span> A());</span><br><span class="line">        test(<span class="keyword">new</span> B());</span><br><span class="line">    &#125;</span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>运行结果:</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">Testing x of type class reflect.csdn.A</span><br><span class="line">x instanceof A true</span><br><span class="line">x instanceof B false</span><br><span class="line">A.isInstance(x) true</span><br><span class="line">B.isInstance(x) false</span><br><span class="line">x.getClass() == A.class true</span><br><span class="line">x.getClass() == B.class false</span><br><span class="line">x.getClass().equals(A.class)) true</span><br><span class="line">x.getClass().equals(B.class)) false</span><br><span class="line">Testing x of type class reflect.csdn.B</span><br><span class="line">x instanceof A true</span><br><span class="line">x instanceof B true</span><br><span class="line">A.isInstance(x) true</span><br><span class="line">B.isInstance(x) true</span><br><span class="line">x.getClass() == A.class false</span><br><span class="line">x.getClass() == B.class true</span><br><span class="line">x.getClass().equals(A.class)) false</span><br><span class="line">x.getClass().equals(B.class)) true</span><br><span class="line"> </span><br><span class="line">Process finished with exit code 0</span><br></pre></td></tr></table></figure>

<p>到此关于Class对象相关的知识点都分析完了，下面将结合Class对象的知识点分析反射技术。</p>
<hr>
<h2 id="3-理解反射技术"><a href="#3-理解反射技术" class="headerlink" title="3. 理解反射技术"></a>3. 理解反射技术</h2><p>反射机制是在运行状态中，对于任意一个类，都能够知道这个类的所有属性和方法；对于任意一个对象，都能够调用它的任意一个方法和属性，这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。一直以来反射技术都是Java中的闪亮点，这也是目前大部分框架(如<code>Spring/Mybatis</code>等)得以实现的支柱。在Java中，<code>Class</code>类与<code>java.lang.reflec</code>t类库一起对反射技术进行了全力的支持。在反射包中，我们常用的类主要有Constructor类表示的是Class 对象所表示的类的构造方法，利用它可以在运行时动态创建对象、Field表示Class对象所表示的类的成员变量，通过它可以在运行时动态修改成员变量的属性值(包含private)、Method表示Class对象所表示的类的成员方法，通过它可以动态调用对象的方法(包含private)，下面将对这几个重要类进行分别说明。</p>
<h3 id="3-1-Constructor类及其用法"><a href="#3-1-Constructor类及其用法" class="headerlink" title="3.1 Constructor类及其用法"></a>3.1 Constructor类及其用法</h3><p>Constructor类存在于反射包(<code>java.lang.reflect</code>)中，反映的是Class 对象所表示的类的构造方法。获取Constructor对象是通过Class类中的方法获取的，Class类与Constructor相关的主要方法如下：</p>
<table>
<thead>
<tr>
<th>方法返回值</th>
<th>方法名称</th>
<th>方法说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>static Class&lt;?&gt;</code></td>
<td>forName(String className)</td>
<td>返回与带有给定字符串名的类或接口相关联的 Class 对象。</td>
</tr>
<tr>
<td><code>Constructor&lt;T&gt;</code></td>
<td><code>getConstructor(Class&lt;?&gt;... parameterTypes)</code></td>
<td>返回指定参数类型、具有public访问权限的构造函数对象</td>
</tr>
<tr>
<td><code>Constructor&lt;?&gt;[]</code></td>
<td>getConstructors()</td>
<td>返回所有具有public访问权限的构造函数的Constructor对象数组</td>
</tr>
<tr>
<td><code>Constructor&lt;T&gt;</code></td>
<td><code>getDeclaredConstructor(Class&lt;?&gt;... parameterTypes)</code></td>
<td>返回指定参数类型、所有声明的（包括private）构造函数对象</td>
</tr>
<tr>
<td><code>Constructor&lt;?&gt;[]</code></td>
<td><code>getDeclaredConstructor()</code></td>
<td>返回所有声明的（包括private）构造函数对象</td>
</tr>
<tr>
<td>T</td>
<td>newInstance()</td>
<td>创建此 Class 对象所表示的类的一个新实例。</td>
</tr>
</tbody></table>
<p>下面看一个简单例子来了解Constructor对象的使用：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> reflect;</span><br><span class="line"> </span><br><span class="line"><span class="keyword">import</span> java.io.Serializable;</span><br><span class="line"><span class="keyword">import</span> java.lang.reflect.Constructor;</span><br><span class="line"> </span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* Created by zejian on 2017/5/1.</span></span><br><span class="line"><span class="comment">* Blog : http://blog.csdn.net/javazejian [原文地址,请尊重原创]</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ReflectDemo</span> <span class="keyword">implements</span> <span class="title">Serializable</span></span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line"> </span><br><span class="line">        Class&lt;?&gt; clazz = <span class="keyword">null</span>;</span><br><span class="line"> </span><br><span class="line">        <span class="comment">//获取Class对象的引用</span></span><br><span class="line">        clazz = Class.forName(<span class="string">"reflect.User"</span>);</span><br><span class="line"> </span><br><span class="line">        <span class="comment">//第一种方法，实例化默认构造方法，User必须无参构造函数,否则将抛异常</span></span><br><span class="line">        User user = (User) clazz.newInstance();</span><br><span class="line">        user.setAge(<span class="number">20</span>);</span><br><span class="line">        user.setName(<span class="string">"Rollen"</span>);</span><br><span class="line">        System.out.println(user);</span><br><span class="line"> </span><br><span class="line">        System.out.println(<span class="string">"--------------------------------------------"</span>);</span><br><span class="line"> </span><br><span class="line">        <span class="comment">//获取带String参数的public构造函数</span></span><br><span class="line">        Constructor cs1 =clazz.getConstructor(String.class);</span><br><span class="line">        <span class="comment">//创建User</span></span><br><span class="line">        User user1= (User) cs1.newInstance(<span class="string">"xiaolong"</span>);</span><br><span class="line">        user1.setAge(<span class="number">22</span>);</span><br><span class="line">        System.out.println(<span class="string">"user1:"</span>+user1.toString());</span><br><span class="line"> </span><br><span class="line">        System.out.println(<span class="string">"--------------------------------------------"</span>);</span><br><span class="line"> </span><br><span class="line">        <span class="comment">//取得指定带int和String参数构造函数,该方法是私有构造private</span></span><br><span class="line">        Constructor cs2=clazz.getDeclaredConstructor(<span class="keyword">int</span>.class,String.class);</span><br><span class="line">        <span class="comment">//由于是private必须设置可访问</span></span><br><span class="line">        cs2.setAccessible(<span class="keyword">true</span>);</span><br><span class="line">        <span class="comment">//创建user对象</span></span><br><span class="line">        User user2= (User) cs2.newInstance(<span class="number">25</span>,<span class="string">"lidakang"</span>);</span><br><span class="line">        System.out.println(<span class="string">"user2:"</span>+user2.toString());</span><br><span class="line"> </span><br><span class="line">        System.out.println(<span class="string">"--------------------------------------------"</span>);</span><br><span class="line"> </span><br><span class="line">        <span class="comment">//获取所有构造包含private</span></span><br><span class="line">        Constructor&lt;?&gt; cons[] = clazz.getDeclaredConstructors();</span><br><span class="line">        <span class="comment">// 查看每个构造方法需要的参数</span></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; cons.length; i++) &#123;</span><br><span class="line">            <span class="comment">//获取构造函数参数类型</span></span><br><span class="line">            Class&lt;?&gt; clazzs[] = cons[i].getParameterTypes();</span><br><span class="line">            System.out.println(<span class="string">"构造函数["</span>+i+<span class="string">"]:"</span>+cons[i].toString() );</span><br><span class="line">            System.out.print(<span class="string">"参数类型["</span>+i+<span class="string">"]:("</span>);</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">0</span>; j &lt; clazzs.length; j++) &#123;</span><br><span class="line">                <span class="keyword">if</span> (j == clazzs.length - <span class="number">1</span>)</span><br><span class="line">                    System.out.print(clazzs[j].getName());</span><br><span class="line">                <span class="keyword">else</span></span><br><span class="line">                    System.out.print(clazzs[j].getName() + <span class="string">","</span>);</span><br><span class="line">            &#125;</span><br><span class="line">            System.out.println(<span class="string">")"</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">User</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">int</span> age;</span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">User</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">User</span><span class="params">(String name)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>();</span><br><span class="line">        <span class="keyword">this</span>.name = name;</span><br><span class="line">    &#125;</span><br><span class="line"> </span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 私有构造</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> age</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> name</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="title">User</span><span class="params">(<span class="keyword">int</span> age, String name)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>();</span><br><span class="line">        <span class="keyword">this</span>.age = age;</span><br><span class="line">        <span class="keyword">this</span>.name = name;</span><br><span class="line">    &#125;</span><br><span class="line"> </span><br><span class="line">  <span class="comment">//..........省略set 和 get方法</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>运行结果：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">User [age=20, name=Rollen]</span><br><span class="line">--------------------------------------------</span><br><span class="line">user1:User [age=22, name=xiaolong]</span><br><span class="line">--------------------------------------------</span><br><span class="line">user2:User [age=25, name=lidakang]</span><br><span class="line">--------------------------------------------</span><br><span class="line">构造函数[0]:private reflect.User(int,java.lang.String)</span><br><span class="line">参数类型[0]:(int,java.lang.String)</span><br><span class="line">构造函数[1]:public reflect.User(java.lang.String)</span><br><span class="line">参数类型[1]:(java.lang.String)</span><br><span class="line">构造函数[2]:public reflect.User()</span><br><span class="line">参数类型[2]:()123456789101112</span><br></pre></td></tr></table></figure>

<p>关于Constructor类本身一些常用方法如下(仅部分，其他可查API)，</p>
<table>
<thead>
<tr>
<th>方法返回值</th>
<th>方法名称</th>
<th>方法说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>Class&lt;T&gt;</code></td>
<td><code>getDeclaringClass()</code></td>
<td>返回 Class 对象，该对象表示声明由此 Constructor 对象表示的构造方法的类,其实就是返回真实类型（不包含参数）</td>
</tr>
<tr>
<td><code>Type[]</code></td>
<td><code>getGenericParameterTypes()</code></td>
<td>按照声明顺序返回一组 Type 对象，返回的就是 Constructor对象构造函数的形参类型。</td>
</tr>
<tr>
<td><code>String</code></td>
<td><code>getName()</code></td>
<td>以字符串形式返回此构造方法的名称。</td>
</tr>
<tr>
<td><code>Class&lt;?&gt;[]</code></td>
<td><code>getParameterTypes()</code></td>
<td>按照声明顺序返回一组 Class 对象，即返回Constructor 对象所表示构造方法的形参类型</td>
</tr>
<tr>
<td><code>T</code></td>
<td><code>newInstance(Object... initargs)</code></td>
<td>使用此 Constructor对象表示的构造函数来创建新实例</td>
</tr>
<tr>
<td>String</td>
<td><code>toGenericString()</code></td>
<td>返回描述此 Constructor 的字符串，其中包括类型参数。</td>
</tr>
</tbody></table>
<p>代码演示如下：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line">Constructor cs3=clazz.getDeclaredConstructor(<span class="keyword">int</span>.class,String.class);</span><br><span class="line"> </span><br><span class="line">System.out.println(<span class="string">"-----getDeclaringClass-----"</span>);</span><br><span class="line">Class uclazz=cs3.getDeclaringClass();</span><br><span class="line"><span class="comment">//Constructor对象表示的构造方法的类</span></span><br><span class="line">System.out.println(<span class="string">"构造方法的类:"</span>+uclazz.getName());</span><br><span class="line"> </span><br><span class="line">System.out.println(<span class="string">"-----getGenericParameterTypes-----"</span>);</span><br><span class="line"><span class="comment">//对象表示此 Constructor 对象所表示的方法的形参类型</span></span><br><span class="line">Type[] tps=cs3.getGenericParameterTypes();</span><br><span class="line"><span class="keyword">for</span> (Type tp:tps) &#123;</span><br><span class="line">    System.out.println(<span class="string">"参数名称tp:"</span>+tp);</span><br><span class="line">&#125;</span><br><span class="line">System.out.println(<span class="string">"-----getParameterTypes-----"</span>);</span><br><span class="line"><span class="comment">//获取构造函数参数类型</span></span><br><span class="line">Class&lt;?&gt; clazzs[] = cs3.getParameterTypes();</span><br><span class="line"><span class="keyword">for</span> (Class claz:clazzs) &#123;</span><br><span class="line">    System.out.println(<span class="string">"参数名称:"</span>+claz.getName());</span><br><span class="line">&#125;</span><br><span class="line">System.out.println(<span class="string">"-----getName-----"</span>);</span><br><span class="line"><span class="comment">//以字符串形式返回此构造方法的名称</span></span><br><span class="line">System.out.println(<span class="string">"getName:"</span>+cs3.getName());</span><br><span class="line"> </span><br><span class="line">System.out.println(<span class="string">"-----getoGenericString-----"</span>);</span><br><span class="line"><span class="comment">//返回描述此 Constructor 的字符串，其中包括类型参数。</span></span><br><span class="line">System.out.println(<span class="string">"getoGenericString():"</span>+cs3.toGenericString());</span><br><span class="line"> </span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">输出结果:</span></span><br><span class="line"><span class="comment">-----getDeclaringClass-----</span></span><br><span class="line"><span class="comment">构造方法的类:reflect.User</span></span><br><span class="line"><span class="comment">-----getGenericParameterTypes-----</span></span><br><span class="line"><span class="comment">参数名称tp:int</span></span><br><span class="line"><span class="comment">参数名称tp:class java.lang.String</span></span><br><span class="line"><span class="comment">-----getParameterTypes-----</span></span><br><span class="line"><span class="comment">参数名称:int</span></span><br><span class="line"><span class="comment">参数名称:java.lang.String</span></span><br><span class="line"><span class="comment">-----getName-----</span></span><br><span class="line"><span class="comment">getName:reflect.User</span></span><br><span class="line"><span class="comment">-----getoGenericString-----</span></span><br><span class="line"><span class="comment">getoGenericString():private reflect.User(int,java.lang.String)</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure>

<p>其中关于Type类型这里简单说明一下，Type 是 Java 编程语言中所有类型的公共高级接口。它们包括原始类型、参数化类型、数组类型、类型变量和基本类型。<code>getGenericParameterTypes</code> 与 <code>getParameterTypes</code> 都是获取构成函数的参数类型，前者返回的是Type类型，后者返回的是Class类型，由于Type顶级接口，Class也实现了该接口，因此Class类是Type的子类，Type 表示的全部类型而每个Class对象表示一个具体类型的实例，如<code>String.class</code>仅代表String类型。由此看来Type与 Class 表示类型几乎是相同的，只不过 Type表示的范围比Class要广得多而已。当然Type还有其他子类，如：</p>
<ul>
<li>TypeVariable：表示类型参数，可以有上界，比如：T extends Number</li>
<li>ParameterizedType：表示参数化的类型，有原始类型和具体的类型参数，比如：<code>List&lt;String&gt;</code></li>
<li>WildcardType：表示通配符类型，比如：?, ? extends Number, ? super Integer</li>
</ul>
<p>通过以上的分析，对于Constructor类已有比较清晰的理解，利用好Class类和Constructor类，我们可以在运行时动态创建任意对象，从而突破必须在编译期知道确切类型的障碍。</p>
<h3 id="3-2-Field类及其用法"><a href="#3-2-Field类及其用法" class="headerlink" title="3.2 Field类及其用法"></a>3.2 Field类及其用法</h3><p>Field 提供有关类或接口的单个字段的信息，以及对它的动态访问权限。反射的字段可能是一个类（静态）字段或实例字段。同样的道理，我们可以通过Class类的提供的方法来获取代表字段信息的Field对象，Class类与Field对象相关方法如下：</p>
<table>
<thead>
<tr>
<th>方法返回值</th>
<th>方法名称</th>
<th>方法说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>Field</code></td>
<td><code>getDeclaredField(String name)</code></td>
<td>获取指定name名称的(包含private修饰的)字段，不包括继承的字段</td>
</tr>
<tr>
<td><code>Field[]</code></td>
<td><code>getDeclaredField()</code></td>
<td>获取Class对象所表示的类或接口的所有(包含private修饰的)字段,不包括继承的字段</td>
</tr>
<tr>
<td><code>Field</code></td>
<td><code>getField(String name)</code></td>
<td>获取指定name名称、具有public修饰的字段，包含继承字段</td>
</tr>
<tr>
<td><code>Field[]</code></td>
<td><code>getField()</code></td>
<td>获取修饰符为public的字段，包含继承字段</td>
</tr>
</tbody></table>
<p>下面的代码演示了上述方法的使用过程</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* Created by zejian on 2017/5/1.</span></span><br><span class="line"><span class="comment">* Blog : http://blog.csdn.net/javazejian [原文地址,请尊重原创]</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ReflectField</span> </span>&#123;</span><br><span class="line"> </span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> ClassNotFoundException, NoSuchFieldException </span>&#123;</span><br><span class="line">        Class&lt;?&gt; clazz = Class.forName(<span class="string">"reflect.Student"</span>);</span><br><span class="line">        <span class="comment">//获取指定字段名称的Field类,注意字段修饰符必须为public而且存在该字段,</span></span><br><span class="line">        <span class="comment">// 否则抛NoSuchFieldException</span></span><br><span class="line">        Field field = clazz.getField(<span class="string">"age"</span>);</span><br><span class="line">        System.out.println(<span class="string">"field:"</span>+field);</span><br><span class="line"> </span><br><span class="line">        <span class="comment">//获取所有修饰符为public的字段,包含父类字段,注意修饰符为public才会获取</span></span><br><span class="line">        Field fields[] = clazz.getFields();</span><br><span class="line">        <span class="keyword">for</span> (Field f:fields) &#123;</span><br><span class="line">            System.out.println(<span class="string">"f:"</span>+f.getDeclaringClass());</span><br><span class="line">        &#125;</span><br><span class="line"> </span><br><span class="line">        System.out.println(<span class="string">"================getDeclaredFields===================="</span>);</span><br><span class="line">        <span class="comment">//获取当前类所字段(包含private字段),注意不包含父类的字段</span></span><br><span class="line">        Field fields2[] = clazz.getDeclaredFields();</span><br><span class="line">        <span class="keyword">for</span> (Field f:fields2) &#123;</span><br><span class="line">            System.out.println(<span class="string">"f2:"</span>+f.getDeclaringClass());</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">//获取指定字段名称的Field类,可以是任意修饰符的自动,注意不包含父类的字段</span></span><br><span class="line">        Field field2 = clazz.getDeclaredField(<span class="string">"desc"</span>);</span><br><span class="line">        System.out.println(<span class="string">"field2:"</span>+field2);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">      输出结果:</span></span><br><span class="line"><span class="comment">     field:public int reflect.Person.age</span></span><br><span class="line"><span class="comment">     f:public java.lang.String reflect.Student.desc</span></span><br><span class="line"><span class="comment">     f:public int reflect.Person.age</span></span><br><span class="line"><span class="comment">     f:public java.lang.String reflect.Person.name</span></span><br><span class="line"><span class="comment"> </span></span><br><span class="line"><span class="comment">     ================getDeclaredFields====================</span></span><br><span class="line"><span class="comment">     f2:public java.lang.String reflect.Student.desc</span></span><br><span class="line"><span class="comment">     f2:private int reflect.Student.score</span></span><br><span class="line"><span class="comment">     field2:public java.lang.String reflect.Student.desc</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Person</span></span>&#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">int</span> age;</span><br><span class="line">    <span class="keyword">public</span> String name;</span><br><span class="line">    <span class="comment">//省略set和get方法</span></span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Student</span> <span class="keyword">extends</span> <span class="title">Person</span></span>&#123;</span><br><span class="line">    <span class="keyword">public</span> String desc;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">int</span> score;</span><br><span class="line">    <span class="comment">//省略set和get方法</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>上述方法需要注意的是，如果我们不期望获取其父类的字段，则需使用Class类的getDeclaredField/getDeclaredFields方法来获取字段即可，倘若需要连带获取到父类的字段，那么请使用Class类的getField/getFields，但是也只能获取到public修饰的的字段，无法获取父类的私有字段。下面将通过Field类本身的方法对指定类属性赋值，代码演示如下：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//获取Class对象引用</span></span><br><span class="line">Class&lt;?&gt; clazz = Class.forName(<span class="string">"reflect.Student"</span>);</span><br><span class="line"> </span><br><span class="line">Student st= (Student) clazz.newInstance();</span><br><span class="line"><span class="comment">//获取父类public字段并赋值</span></span><br><span class="line">Field ageField = clazz.getField(<span class="string">"age"</span>);</span><br><span class="line">ageField.set(st,<span class="number">18</span>);</span><br><span class="line">Field nameField = clazz.getField(<span class="string">"name"</span>);</span><br><span class="line">nameField.set(st,<span class="string">"Lily"</span>);</span><br><span class="line"> </span><br><span class="line"><span class="comment">//只获取当前类的字段,不获取父类的字段</span></span><br><span class="line">Field descField = clazz.getDeclaredField(<span class="string">"desc"</span>);</span><br><span class="line">descField.set(st,<span class="string">"I am student"</span>);</span><br><span class="line">Field scoreField = clazz.getDeclaredField(<span class="string">"score"</span>);</span><br><span class="line"><span class="comment">//设置可访问，score是private的</span></span><br><span class="line">scoreField.setAccessible(<span class="keyword">true</span>);</span><br><span class="line">scoreField.set(st,<span class="number">88</span>);</span><br><span class="line">System.out.println(st.toString());</span><br><span class="line"> </span><br><span class="line"><span class="comment">//输出结果：Student&#123;age=18, name='Lily ,desc='I am student', score=88&#125;</span></span><br><span class="line"> </span><br><span class="line"><span class="comment">//获取字段值</span></span><br><span class="line">System.out.println(scoreField.get(st));</span><br><span class="line"><span class="comment">// 88123456789101112131415161718192021222324</span></span><br></pre></td></tr></table></figure>

<p>其中的<code>set(Object obj, Object value)</code>方法是Field类本身的方法，用于设置字段的值，而<code>get(Object obj)</code>则是获取字段的值，当然关于Field类还有其他常用的方法如下：</p>
<table>
<thead>
<tr>
<th>方法返回值</th>
<th>方法名称</th>
<th>方法说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>void</code></td>
<td><code>set(Object obj, Object value)</code></td>
<td>将指定对象变量上此 Field 对象表示的字段设置为指定的新值。</td>
</tr>
<tr>
<td><code>Object</code></td>
<td><code>get(Object obj)</code></td>
<td>返回指定对象上此 Field 表示的字段的值</td>
</tr>
<tr>
<td><code>Class&lt;?&gt;</code></td>
<td><code>getType()</code></td>
<td>返回一个 Class 对象，它标识了此Field 对象所表示字段的声明类型。</td>
</tr>
<tr>
<td><code>boolean</code></td>
<td><code>isEnumConstant()</code></td>
<td>如果此字段表示枚举类型的元素则返回 true；否则返回 false</td>
</tr>
<tr>
<td><code>String</code></td>
<td><code>toGenericString()</code></td>
<td>返回一个描述此 Field（包括其一般类型）的字符串</td>
</tr>
<tr>
<td><code>String</code></td>
<td><code>getName()</code></td>
<td>返回此 Field 对象表示的字段的名称</td>
</tr>
<tr>
<td><code>Class&lt;?&gt;</code></td>
<td><code>getDeclaringClass()</code></td>
<td>返回表示类或接口的 Class 对象，该类或接口声明由此 Field 对象表示的字段</td>
</tr>
<tr>
<td>void</td>
<td>setAccessible(boolean flag)</td>
<td>将此对象的 accessible 标志设置为指示的布尔值,即设置其可访问性</td>
</tr>
</tbody></table>
<p>上述方法可能是较为常用的，事实上在设置值的方法上，Field类还提供了专门针对基本数据类型的方法，如setInt()/getInt()、setBoolean()/getBoolean、setChar()/getChar()等等方法，这里就不全部列出了，需要时查API文档即可。需要特别注意的是被final关键字修饰的Field字段是安全的，在运行时可以接收任何修改，但最终其实际值是不会发生改变的。</p>
<h3 id="3-3-Method类及其用法"><a href="#3-3-Method类及其用法" class="headerlink" title="3.3 Method类及其用法"></a>3.3 Method类及其用法</h3><p>Method 提供关于类或接口上单独某个方法（以及如何访问该方法）的信息，所反映的方法可能是类方法或实例方法（包括抽象方法）。下面是Class类获取Method对象相关的方法：</p>
<table>
<thead>
<tr>
<th>方法返回值</th>
<th>方法名称</th>
<th>方法说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>Method</code></td>
<td><code>getDeclaredMethod(String name, Class&lt;?&gt;... parameterTypes)</code></td>
<td>返回一个指定参数的Method对象，该对象反映此 Class 对象所表示的类或接口的指定已声明方法。</td>
</tr>
<tr>
<td><code>Method[]</code></td>
<td><code>getDeclaredMethod()</code></td>
<td>返回 Method 对象的一个数组，这些对象反映此 Class 对象表示的类或接口声明的所有方法，包括公共、保护、默认（包）访问和私有方法，但不包括继承的方法。</td>
</tr>
<tr>
<td><code>Method</code></td>
<td><code>getMethod(String name, Class&lt;?&gt;... parameterTypes)</code></td>
<td>返回一个 Method 对象，它反映此 Class 对象所表示的类或接口的指定公共成员方法。</td>
</tr>
<tr>
<td><code>Method[]</code></td>
<td><code>getMethods()</code></td>
<td>返回一个包含某些 Method 对象的数组，这些对象反映此 Class 对象所表示的类或接口（包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口）的公共 member 方法。</td>
</tr>
</tbody></table>
<p>同样通过案例演示上述方法：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.lang.reflect.Method;</span><br><span class="line"> </span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* Created by zejian on 2017/5/1.</span></span><br><span class="line"><span class="comment">* Blog : http://blog.csdn.net/javazejian [原文地址,请尊重原创]</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ReflectMethod</span>  </span>&#123;</span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> ClassNotFoundException, NoSuchMethodException </span>&#123;</span><br><span class="line"> </span><br><span class="line">        Class clazz = Class.forName(<span class="string">"reflect.Circle"</span>);</span><br><span class="line"> </span><br><span class="line">        <span class="comment">//根据参数获取public的Method,包含继承自父类的方法</span></span><br><span class="line">        Method method = clazz.getMethod(<span class="string">"draw"</span>,<span class="keyword">int</span>.class,String.class);</span><br><span class="line"> </span><br><span class="line">        System.out.println(<span class="string">"method:"</span>+method);</span><br><span class="line"> </span><br><span class="line">        <span class="comment">//获取所有public的方法:</span></span><br><span class="line">        Method[] methods =clazz.getMethods();</span><br><span class="line">        <span class="keyword">for</span> (Method m:methods)&#123;</span><br><span class="line">            System.out.println(<span class="string">"m::"</span>+m);</span><br><span class="line">        &#125;</span><br><span class="line"> </span><br><span class="line">        System.out.println(<span class="string">"========================================="</span>);</span><br><span class="line"> </span><br><span class="line">        <span class="comment">//获取当前类的方法包含private,该方法无法获取继承自父类的method</span></span><br><span class="line">        Method method1 = clazz.getDeclaredMethod(<span class="string">"drawCircle"</span>);</span><br><span class="line">        System.out.println(<span class="string">"method1::"</span>+method1);</span><br><span class="line">        <span class="comment">//获取当前类的所有方法包含private,该方法无法获取继承自父类的method</span></span><br><span class="line">        Method[] methods1=clazz.getDeclaredMethods();</span><br><span class="line">        <span class="keyword">for</span> (Method m:methods1)&#123;</span><br><span class="line">            System.out.println(<span class="string">"m1::"</span>+m);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"> </span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     输出结果:</span></span><br><span class="line"><span class="comment">     method:public void reflect.Shape.draw(int,java.lang.String)</span></span><br><span class="line"><span class="comment"> </span></span><br><span class="line"><span class="comment">     m::public int reflect.Circle.getAllCount()</span></span><br><span class="line"><span class="comment">     m::public void reflect.Shape.draw()</span></span><br><span class="line"><span class="comment">     m::public void reflect.Shape.draw(int,java.lang.String)</span></span><br><span class="line"><span class="comment">     m::public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException</span></span><br><span class="line"><span class="comment">     m::public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException</span></span><br><span class="line"><span class="comment">     m::public final void java.lang.Object.wait() throws java.lang.InterruptedException</span></span><br><span class="line"><span class="comment">     m::public boolean java.lang.Object.equals(java.lang.Object)</span></span><br><span class="line"><span class="comment">     m::public java.lang.String java.lang.Object.toString()</span></span><br><span class="line"><span class="comment">     m::public native int java.lang.Object.hashCode()</span></span><br><span class="line"><span class="comment">     m::public final native java.lang.Class java.lang.Object.getClass()</span></span><br><span class="line"><span class="comment">     m::public final native void java.lang.Object.notify()</span></span><br><span class="line"><span class="comment">     m::public final native void java.lang.Object.notifyAll()</span></span><br><span class="line"><span class="comment"> </span></span><br><span class="line"><span class="comment">     =========================================</span></span><br><span class="line"><span class="comment">     method1::private void reflect.Circle.drawCircle()</span></span><br><span class="line"><span class="comment"> </span></span><br><span class="line"><span class="comment">     m1::public int reflect.Circle.getAllCount()</span></span><br><span class="line"><span class="comment">     m1::private void reflect.Circle.drawCircle()</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Shape</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">draw</span><span class="params">()</span></span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"draw"</span>);</span><br><span class="line">    &#125;</span><br><span class="line"> </span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">draw</span><span class="params">(<span class="keyword">int</span> count , String name)</span></span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"draw "</span>+ name +<span class="string">",count="</span>+count);</span><br><span class="line">    &#125;</span><br><span class="line"> </span><br><span class="line">&#125;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Circle</span> <span class="keyword">extends</span> <span class="title">Shape</span></span>&#123;</span><br><span class="line"> </span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">drawCircle</span><span class="params">()</span></span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"drawCircle"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">getAllCount</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">100</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;<span class="number">1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980</span></span><br></pre></td></tr></table></figure>

<p>在通过getMethods方法获取Method对象时，会把父类的方法也获取到，如上的输出结果，把Object类的方法都打印出来了。而getDeclaredMethod/getDeclaredMethods方法都只能获取当前类的方法。我们在使用时根据情况选择即可。下面将演示通过Method对象调用指定类的方法：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line">Class clazz = Class.forName(<span class="string">"reflect.Circle"</span>);</span><br><span class="line"><span class="comment">//创建对象</span></span><br><span class="line">Circle circle = (Circle) clazz.newInstance();</span><br><span class="line"> </span><br><span class="line"><span class="comment">//获取指定参数的方法对象Method</span></span><br><span class="line">Method method = clazz.getMethod(<span class="string">"draw"</span>,<span class="keyword">int</span>.class,String.class);</span><br><span class="line"> </span><br><span class="line"><span class="comment">//通过Method对象的invoke(Object obj,Object... args)方法调用</span></span><br><span class="line">method.invoke(circle,<span class="number">15</span>,<span class="string">"圈圈"</span>);</span><br><span class="line"> </span><br><span class="line"><span class="comment">//对私有无参方法的操作</span></span><br><span class="line">Method method1 = clazz.getDeclaredMethod(<span class="string">"drawCircle"</span>);</span><br><span class="line"><span class="comment">//修改私有方法的访问标识</span></span><br><span class="line">method1.setAccessible(<span class="keyword">true</span>);</span><br><span class="line">method1.invoke(circle);</span><br><span class="line"> </span><br><span class="line"><span class="comment">//对有返回值得方法操作</span></span><br><span class="line">Method method2 =clazz.getDeclaredMethod(<span class="string">"getAllCount"</span>);</span><br><span class="line">Integer count = (Integer) method2.invoke(circle);</span><br><span class="line">System.out.println(<span class="string">"count:"</span>+count);</span><br><span class="line"> </span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">    输出结果:</span></span><br><span class="line"><span class="comment">    draw 圈圈,count=15</span></span><br><span class="line"><span class="comment">    drawCircle</span></span><br><span class="line"><span class="comment">    count:100</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure>

<p>在上述代码中调用方法，使用了Method类的<code>invoke(Object obj,Object... args)</code>第一个参数代表调用的对象，第二个参数传递的调用方法的参数。这样就完成了类方法的动态调用。</p>
<table>
<thead>
<tr>
<th>方法返回值</th>
<th>方法名称</th>
<th>方法说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>Object</code></td>
<td><code>invoke(Object obj, Object... args)</code></td>
<td>对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。</td>
</tr>
<tr>
<td><code>Class&lt;?&gt;</code></td>
<td><code>getReturnType()</code></td>
<td>返回一个 Class 对象，该对象描述了此 Method 对象所表示的方法的正式返回类型,即方法的返回类型</td>
</tr>
<tr>
<td>Type</td>
<td><code>getGenericReturnType()</code></td>
<td>返回表示由此 Method 对象所表示方法的正式返回类型的 Type 对象，也是方法的返回类型。</td>
</tr>
<tr>
<td><code>Class&lt;?&gt;[]</code></td>
<td><code>getParameterTypes()</code></td>
<td>按照声明顺序返回 Class 对象的数组，这些对象描述了此 Method 对象所表示的方法的形参类型。即返回方法的参数类型组成的数组</td>
</tr>
<tr>
<td><code>Type[]</code></td>
<td><code>getGenericParameterTypes()</code></td>
<td>按照声明顺序返回 Type 对象的数组，这些对象描述了此 Method 对象所表示的方法的形参类型的，也是返回方法的参数类型</td>
</tr>
<tr>
<td><code>String</code></td>
<td><code>getName()</code></td>
<td>以 String 形式返回此 Method 对象表示的方法名称，即返回方法的名称</td>
</tr>
<tr>
<td><code>boolean</code></td>
<td><code>isVarArgs()</code></td>
<td>判断方法是否带可变参数，如果将此方法声明为带有可变数量的参数，则返回 true；否则，返回 false。</td>
</tr>
<tr>
<td><code>String</code></td>
<td><code>toGenericString()</code></td>
<td>返回描述此 Method 的字符串，包括类型参数。</td>
</tr>
</tbody></table>
<p>getReturnType方法/getGenericReturnType方法都是获取Method对象表示的方法的返回类型，只不过前者返回的Class类型后者返回的Type(前面已分析过)，Type就是一个接口而已，在Java8中新增一个默认的方法实现，返回的就参数类型信息</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">Type</span> </span>&#123;</span><br><span class="line">    <span class="comment">//1.8新增</span></span><br><span class="line">    <span class="function"><span class="keyword">default</span> String <span class="title">getTypeName</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> toString();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>而getParameterTypes/getGenericParameterTypes也是同样的道理，都是获取Method对象所表示的方法的参数类型，其他方法与前面的Field和Constructor是类似的。</p>
<h3 id="3-4-反射包中的Array类"><a href="#3-4-反射包中的Array类" class="headerlink" title="3.4 反射包中的Array类"></a>3.4 反射包中的Array类</h3><p>在Java的<code>java.lang.reflect</code>包中存在着一个可以动态操作数组的类，Array，它提供了动态创建和访问 Java 数组的方法。Array 允许在执行 get 或 set 操作进行取值和赋值。在Class类中与数组关联的方法是：</p>
<table>
<thead>
<tr>
<th>方法返回值</th>
<th>方法名称</th>
<th>方法说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>Class&lt;?&gt;</code></td>
<td><code>getComponentType()</code></td>
<td>返回表示数组元素类型的 Class，即数组的类型</td>
</tr>
<tr>
<td><code>boolean</code></td>
<td><code>isArray()</code></td>
<td>判定此 Class 对象是否表示一个数组类。</td>
</tr>
</tbody></table>
<p>java.lang.reflect.Array中的常用静态方法如下：</p>
<table>
<thead>
<tr>
<th>方法返回值</th>
<th>方法名称</th>
<th>方法说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>static Object</code></td>
<td><code>set(Object array, int index)</code></td>
<td>返回指定数组对象中索引组件的值。</td>
</tr>
<tr>
<td><code>static int</code></td>
<td><code>getLength(Object array)</code></td>
<td>以 int 形式返回指定数组对象的长度</td>
</tr>
<tr>
<td><code>static object</code></td>
<td><code>newInstance(Class&lt;?&gt; componentType, int... dimensions)</code></td>
<td>创建一个具有指定类型和维度的新数组。</td>
</tr>
<tr>
<td><code>static Object</code></td>
<td><code>newInstance(Class&lt;?&gt; componentType, int length)</code></td>
<td>创建一个具有指定的组件类型和长度的新数组。</td>
</tr>
<tr>
<td><code>static void</code></td>
<td><code>set(Object array, int index, Object value)</code></td>
<td>将指定数组对象中索引组件的值设置为指定的新值。</td>
</tr>
</tbody></table>
<p>下面通过一个简单例子来演示这些方法</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> reflect;</span><br><span class="line"> </span><br><span class="line"><span class="keyword">import</span> java.lang.reflect.Array;</span><br><span class="line"> </span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* Created by zejian on 2017/5/1.</span></span><br><span class="line"><span class="comment">* Blog : http://blog.csdn.net/javazejian [原文地址,请尊重原创]</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ReflectArray</span> </span>&#123;</span><br><span class="line"> </span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> ClassNotFoundException </span>&#123;</span><br><span class="line">        <span class="keyword">int</span>[] array = &#123; <span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">7</span>, <span class="number">8</span>, <span class="number">9</span> &#125;;</span><br><span class="line">        <span class="comment">//获取数组类型的Class 即int.class</span></span><br><span class="line">        Class&lt;?&gt; clazz = array.getClass().getComponentType();</span><br><span class="line">        <span class="comment">//创建一个具有指定的组件类型和长度的新数组。</span></span><br><span class="line">        <span class="comment">//第一个参数:数组的类型,第二个参数:数组的长度</span></span><br><span class="line">        Object newArr = Array.newInstance(clazz, <span class="number">15</span>);</span><br><span class="line">        <span class="comment">//获取原数组的长度</span></span><br><span class="line">        <span class="keyword">int</span> co = Array.getLength(array);</span><br><span class="line">        <span class="comment">//赋值原数组到新数组</span></span><br><span class="line">        System.arraycopy(array, <span class="number">0</span>, newArr, <span class="number">0</span>, co);</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i:(<span class="keyword">int</span>[]) newArr) &#123;</span><br><span class="line">            System.out.print(i+<span class="string">","</span>);</span><br><span class="line">        &#125;</span><br><span class="line"> </span><br><span class="line">        <span class="comment">//创建了一个长度为10 的字符串数组，</span></span><br><span class="line">        <span class="comment">//接着把索引位置为6 的元素设为"hello world!"，然后再读取索引位置为6 的元素的值</span></span><br><span class="line">        Class clazz2 = Class.forName(<span class="string">"java.lang.String"</span>);</span><br><span class="line"> </span><br><span class="line">        <span class="comment">//创建一个长度为10的字符串数组，在Java中数组也可以作为Object对象</span></span><br><span class="line">        Object array2 = Array.newInstance(clazz2, <span class="number">10</span>);</span><br><span class="line"> </span><br><span class="line">        <span class="comment">//把字符串数组对象的索引位置为6的元素设置为"hello"</span></span><br><span class="line">        Array.set(array2, <span class="number">6</span>, <span class="string">"hello world!"</span>);</span><br><span class="line"> </span><br><span class="line">        <span class="comment">//获得字符串数组对象的索引位置为5的元素的值</span></span><br><span class="line">        String str = (String)Array.get(array2, <span class="number">6</span>);</span><br><span class="line">        System.out.println();</span><br><span class="line">        System.out.println(str);<span class="comment">//hello</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     输出结果:</span></span><br><span class="line"><span class="comment">     1,2,3,4,5,6,7,8,9,0,0,0,0,0,0,</span></span><br><span class="line"><span class="comment">     hello world!</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>通过上述代码演示，确实可以利用Array类和反射相结合动态创建数组，也可以在运行时动态获取和设置数组中元素的值，其实除了上的set/get外Array还专门为8种基本数据类型提供特有的方法，如setInt/getInt、setBoolean/getBoolean，其他依次类推，需要使用是可以查看API文档即可。除了上述动态修改数组长度或者动态创建数组或动态获取值或设置值外，可以利用泛型动态创建泛型数组如下：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">  * 接收一个泛型数组，然后创建一个长度与接收的数组长度一样的泛型数组，</span></span><br><span class="line"><span class="comment">  * 并把接收的数组的元素复制到新创建的数组中，</span></span><br><span class="line"><span class="comment">  * 最后找出新数组中的最小元素，并打印出来</span></span><br><span class="line"><span class="comment">  * <span class="doctag">@param</span> a</span></span><br><span class="line"><span class="comment">  * <span class="doctag">@param</span> &lt;T&gt;</span></span><br><span class="line"><span class="comment">  */</span></span><br><span class="line"> <span class="keyword">public</span>  &lt;T extends Comparable&lt;T&gt;&gt; <span class="function"><span class="keyword">void</span> <span class="title">min</span><span class="params">(T[] a)</span> </span>&#123;</span><br><span class="line">     <span class="comment">//通过反射创建相同类型的数组</span></span><br><span class="line">     T[] b = (T[]) Array.newInstance(a.getClass().getComponentType(), a.length);</span><br><span class="line">     <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; a.length; i++) &#123;</span><br><span class="line">         b[i] = a[i];</span><br><span class="line">     &#125;</span><br><span class="line">     T min = <span class="keyword">null</span>;</span><br><span class="line">     <span class="keyword">boolean</span> flag = <span class="keyword">true</span>;</span><br><span class="line">     <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; b.length; i++) &#123;</span><br><span class="line">         <span class="keyword">if</span> (flag) &#123;</span><br><span class="line">             min = b[i];</span><br><span class="line">             flag = <span class="keyword">false</span>;</span><br><span class="line">         &#125;</span><br><span class="line">         <span class="keyword">if</span> (b[i].compareTo(min) &lt; <span class="number">0</span>) &#123;</span><br><span class="line">             min = b[i];</span><br><span class="line">         &#125;</span><br><span class="line">     &#125;</span><br><span class="line">     System.out.println(min);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>毕竟我们无法直接创建泛型数组，有了Array的动态创建数组的方式这个问题也就迎刃而解了。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//无效语句，编译不通</span></span><br><span class="line">T[] a = <span class="keyword">new</span> T[];<span class="number">12</span></span><br></pre></td></tr></table></figure>

<p>ok~，到这反射中几个重要并且常用的类我们都基本介绍完了，但更重要是，我们应该认识到反射机制并没有什么神奇之处。当通过反射与一个未知类型的对象打交道时，JVM只会简单地检查这个对象，判断该对象属于那种类型，同时也应该知道，在使用反射机制创建对象前，必须确保已加载了这个类的Class对象，当然这点完全不必由我们操作，毕竟只能JVM加载，但必须确保该类的”.class”文件已存在并且JVM能够正确找到。关于Class类的方法在前面我们只是分析了主要的一些方法，其实Class类的API方法挺多的，建议查看一下API文档，浏览一遍，有个印象也是不错的选择，这里仅列出前面没有介绍过又可能用到的API：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">  *    修饰符、父类、实现的接口、注解相关</span></span><br><span class="line"><span class="comment">  */</span></span><br><span class="line"> </span><br><span class="line"><span class="comment">//获取修饰符，返回值可通过Modifier类进行解读</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">native</span> <span class="keyword">int</span> <span class="title">getModifiers</span><span class="params">()</span></span>;</span><br><span class="line"><span class="comment">//获取父类，如果为Object，父类为null</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">native</span> Class&lt;? <span class="keyword">super</span> T&gt; getSuperclass();</span><br><span class="line"><span class="comment">//对于类，为自己声明实现的所有接口，对于接口，为直接扩展的接口，不包括通过父类间接继承来的</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">native</span> Class&lt;?&gt;[] getInterfaces();</span><br><span class="line"><span class="comment">//自己声明的注解</span></span><br><span class="line"><span class="keyword">public</span> Annotation[] getDeclaredAnnotations();</span><br><span class="line"><span class="comment">//所有的注解，包括继承得到的</span></span><br><span class="line"><span class="keyword">public</span> Annotation[] getAnnotations();</span><br><span class="line"><span class="comment">//获取或检查指定类型的注解，包括继承得到的</span></span><br><span class="line"><span class="keyword">public</span> &lt;A extends Annotation&gt; <span class="function">A <span class="title">getAnnotation</span><span class="params">(Class&lt;A&gt; annotationClass)</span></span>;</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">isAnnotationPresent</span><span class="params">(Class&lt;? extends Annotation&gt; annotationClass)</span></span>;</span><br><span class="line"> </span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">  *   内部类相关</span></span><br><span class="line"><span class="comment">  */</span></span><br><span class="line"><span class="comment">//获取所有的public的内部类和接口，包括从父类继承得到的</span></span><br><span class="line"><span class="keyword">public</span> Class&lt;?&gt;[] getClasses();</span><br><span class="line"><span class="comment">//获取自己声明的所有的内部类和接口</span></span><br><span class="line"><span class="keyword">public</span> Class&lt;?&gt;[] getDeclaredClasses();</span><br><span class="line"><span class="comment">//如果当前Class为内部类，获取声明该类的最外部的Class对象</span></span><br><span class="line"><span class="keyword">public</span> Class&lt;?&gt; getDeclaringClass();</span><br><span class="line"><span class="comment">//如果当前Class为内部类，获取直接包含该类的类</span></span><br><span class="line"><span class="keyword">public</span> Class&lt;?&gt; getEnclosingClass();</span><br><span class="line"><span class="comment">//如果当前Class为本地类或匿名内部类，返回包含它的方法</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> Method <span class="title">getEnclosingMethod</span><span class="params">()</span></span>;</span><br><span class="line"> </span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">  *    Class对象类型判断相关</span></span><br><span class="line"><span class="comment">  */</span></span><br><span class="line"><span class="comment">//是否是数组</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">native</span> <span class="keyword">boolean</span> <span class="title">isArray</span><span class="params">()</span></span>; </span><br><span class="line"><span class="comment">//是否是基本类型</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">native</span> <span class="keyword">boolean</span> <span class="title">isPrimitive</span><span class="params">()</span></span>;</span><br><span class="line"><span class="comment">//是否是接口</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">native</span> <span class="keyword">boolean</span> <span class="title">isInterface</span><span class="params">()</span></span>;</span><br><span class="line"><span class="comment">//是否是枚举</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">isEnum</span><span class="params">()</span></span>;</span><br><span class="line"><span class="comment">//是否是注解</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">isAnnotation</span><span class="params">()</span></span>;</span><br><span class="line"><span class="comment">//是否是匿名内部类</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">isAnonymousClass</span><span class="params">()</span></span>;</span><br><span class="line"><span class="comment">//是否是成员类</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">isMemberClass</span><span class="params">()</span></span>;</span><br><span class="line"><span class="comment">//是否是本地类</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">isLocalClass</span><span class="params">()</span></span>;</span><br></pre></td></tr></table></figure>

<p>ok~，本篇到此完结。</p>

      
    </div>
    
    
    

    

    
      <div>
        <div style="padding: 10px 0; margin: 20px auto; width: 90%; text-align: center;">
  <div>请我喝杯茶……</div>
  <button id="rewardButton" disable="enable" onclick="var qr = document.getElementById('QR'); if (qr.style.display === 'none') {qr.style.display='block';} else {qr.style.display='none'}">
    <span>打赏</span>
  </button>
  <div id="QR" style="display: none;">

    
      <div id="wechat" style="display: inline-block">
        <img id="wechat_qr" src="/images/wechat.jpg" alt="Briar·bear 微信支付">
        <p>微信支付</p>
      </div>
    

    
      <div id="alipay" style="display: inline-block">
        <img id="alipay_qr" src="/images/alipay.jpg" alt="Briar·bear 支付宝">
        <p>支付宝</p>
      </div>
    

    

  </div>
</div>

      </div>
    

    

    <footer class="post-footer">
      
        <div class="post-tags">
          
            <a href="/tags/反射/" rel="tag"># 反射</a>
          
            <a href="/tags/JVM/" rel="tag"># JVM</a>
          
            <a href="/tags/转载/" rel="tag"># 转载</a>
          
        </div>
      

      
      
        <div class="post-widgets">
        

        

        
          
          <div id="needsharebutton-postbottom">
            <span class="btn">
              <i class="fa fa-share-alt" aria-hidden="true"></i>
            </span>
          </div>
        
        </div>
      
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/2018/07/09/Java-反射机制的核心原理/" rel="next" title="Java-反射机制的核心原理">
                <i class="fa fa-chevron-left"></i> Java-反射机制的核心原理
              </a>
            
          </div>

          <span class="post-nav-divider"></span>

          <div class="post-nav-prev post-nav-item">
            
              <a href="/2018/07/10/架构系列-负载均衡详解/" rel="prev" title="架构系列-负载均衡详解">
                架构系列-负载均衡详解 <i class="fa fa-chevron-right"></i>
              </a>
            
          </div>
        </div>
      

      
      
    </footer>
  </div>
  
  
  
  </article>



    <div class="post-spread">
      
    </div>
  </div>


          </div>
          


          

  
    <div class="comments" id="comments">
      
        <div id="gitment-container"></div>
      
    </div>

  



        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap">
            文章目录
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview-wrap">
            站点概览
          </li>
        </ul>
      

      <section class="site-overview-wrap sidebar-panel">
        <div class="site-overview">
          <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
            
              <img class="site-author-image" itemprop="image" src="/images/photo.png" alt="Briar·bear">
            
              <p class="site-author-name" itemprop="name">Briar·bear</p>
              <p class="site-description motion-element" itemprop="description">Java程序员成长之路</p>
          </div>

          <nav class="site-state motion-element">

            
              <div class="site-state-item site-state-posts">
              
                <a href="/archives/">
              
                  <span class="site-state-item-count">34</span>
                  <span class="site-state-item-name">日志</span>
                </a>
              </div>
            

            
              
              
              <div class="site-state-item site-state-categories">
                <a href="/categories/index.html">
                  <span class="site-state-item-count">7</span>
                  <span class="site-state-item-name">分类</span>
                </a>
              </div>
            

            
              
              
              <div class="site-state-item site-state-tags">
                <a href="/tags/index.html">
                  <span class="site-state-item-count">24</span>
                  <span class="site-state-item-name">标签</span>
                </a>
              </div>
            

          </nav>

          

          
            <div class="links-of-author motion-element">
                
                  <span class="links-of-author-item">
                    <a href="https://github.com/briarbear" target="_blank" title="GitHub">
                      
                        <i class="fa fa-fw fa-github"></i>GitHub</a>
                  </span>
                
            </div>
          

          
          

          
          

          

        </div>
      </section>

      
      <!--noindex-->
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">

            
              
            

            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-2"><a class="nav-link" href="#1-深入理解Class对象"><span class="nav-text">1. 深入理解Class对象</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#1-1-RRTI的概念以及Class对象引用"><span class="nav-text">1.1 RRTI的概念以及Class对象引用</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#1-2-总结信息"><span class="nav-text">1.2 总结信息</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#2-Class对象的加载及其获取方法"><span class="nav-text">2. Class对象的加载及其获取方法</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#2-1-Class对象的加载"><span class="nav-text">2.1 Class对象的加载</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-2-Class-forName方法"><span class="nav-text">2.2 Class.forName方法</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-3-Class字面常量"><span class="nav-text">2.3 Class字面常量</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-4-理解泛化的Class对象引用"><span class="nav-text">2.4 理解泛化的Class对象引用</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-5-关于类型转换的问题"><span class="nav-text">2.5 关于类型转换的问题</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-5-instanceof-关键字与-isInstance-方法"><span class="nav-text">2.5 instanceof 关键字与 isInstance()方法</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#3-理解反射技术"><span class="nav-text">3. 理解反射技术</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#3-1-Constructor类及其用法"><span class="nav-text">3.1 Constructor类及其用法</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#3-2-Field类及其用法"><span class="nav-text">3.2 Field类及其用法</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#3-3-Method类及其用法"><span class="nav-text">3.3 Method类及其用法</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#3-4-反射包中的Array类"><span class="nav-text">3.4 反射包中的Array类</span></a></li></ol></li></ol></div>
            

          </div>
        </section>
      <!--/noindex-->
      

      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright">&copy; <span itemprop="copyrightYear">2019</span>
  <span class="with-love">
    <i class="fa fa-user"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">Briar·bear</span>

  
</div>


  <div class="powered-by">由 <a class="theme-link" target="_blank" href="https://hexo.io">Hexo</a> 强力驱动</div>



  <span class="post-meta-divider">|</span>



  <div class="theme-info">主题 &mdash; <a class="theme-link" target="_blank" href="https://github.com/iissnan/hexo-theme-next">NexT.Mist</a> v5.1.4</div>




        







        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
      </div>
    

    
      <div id="needsharebutton-float">
        <span class="btn">
          <i class="fa fa-share-alt" aria-hidden="true"></i>
        </span>
      </div>
    

  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  












  
  
    <script type="text/javascript" src="/lib/jquery/index.js?v=2.1.3"></script>
  

  
  
    <script type="text/javascript" src="/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>
  

  
  
    <script type="text/javascript" src="/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>
  

  
  
    <script type="text/javascript" src="/lib/velocity/velocity.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>
  


  


  <script type="text/javascript" src="/js/src/utils.js?v=5.1.4"></script>

  <script type="text/javascript" src="/js/src/motion.js?v=5.1.4"></script>



  
  

  
  <script type="text/javascript" src="/js/src/scrollspy.js?v=5.1.4"></script>
<script type="text/javascript" src="/js/src/post-details.js?v=5.1.4"></script>



  


  <script type="text/javascript" src="/js/src/bootstrap.js?v=5.1.4"></script>



  


  




	





  





  







<!-- LOCAL: You can save these files to your site and update links -->
    
        
        <link rel="stylesheet" href="https://aimingoo.github.io/gitmint/style/default.css">
        <script src="https://aimingoo.github.io/gitmint/dist/gitmint.browser.js"></script>
    
<!-- END LOCAL -->

    

    
      <script type="text/javascript">
      function renderGitment(){
        var gitment = new Gitmint({
            id: window.location.pathname, 
            owner: 'briarbear',
            repo: 'gitment',
            
            lang: "" || navigator.language || navigator.systemLanguage || navigator.userLanguage,
            
            oauth: {
            
            
                client_secret: '2aa927fc78092a27546f7615348dec89f92b9001',
            
                client_id: '512cfb4d4a196b4ee6f6'
            }});
        gitment.render('gitment-container');
      }

      
      renderGitment();
      
      </script>
    







  

  <script type="text/javascript">
    // Popup Window;
    var isfetched = false;
    var isXml = true;
    // Search DB path;
    var search_path = "search.xml";
    if (search_path.length === 0) {
      search_path = "search.xml";
    } else if (/json$/i.test(search_path)) {
      isXml = false;
    }
    var path = "/" + search_path;
    // monitor main search box;

    var onPopupClose = function (e) {
      $('.popup').hide();
      $('#local-search-input').val('');
      $('.search-result-list').remove();
      $('#no-result').remove();
      $(".local-search-pop-overlay").remove();
      $('body').css('overflow', '');
    }

    function proceedsearch() {
      $("body")
        .append('<div class="search-popup-overlay local-search-pop-overlay"></div>')
        .css('overflow', 'hidden');
      $('.search-popup-overlay').click(onPopupClose);
      $('.popup').toggle();
      var $localSearchInput = $('#local-search-input');
      $localSearchInput.attr("autocapitalize", "none");
      $localSearchInput.attr("autocorrect", "off");
      $localSearchInput.focus();
    }

    // search function;
    var searchFunc = function(path, search_id, content_id) {
      'use strict';

      // start loading animation
      $("body")
        .append('<div class="search-popup-overlay local-search-pop-overlay">' +
          '<div id="search-loading-icon">' +
          '<i class="fa fa-spinner fa-pulse fa-5x fa-fw"></i>' +
          '</div>' +
          '</div>')
        .css('overflow', 'hidden');
      $("#search-loading-icon").css('margin', '20% auto 0 auto').css('text-align', 'center');

      $.ajax({
        url: path,
        dataType: isXml ? "xml" : "json",
        async: true,
        success: function(res) {
          // get the contents from search data
          isfetched = true;
          $('.popup').detach().appendTo('.header-inner');
          var datas = isXml ? $("entry", res).map(function() {
            return {
              title: $("title", this).text(),
              content: $("content",this).text(),
              url: $("url" , this).text()
            };
          }).get() : res;
          var input = document.getElementById(search_id);
          var resultContent = document.getElementById(content_id);
          var inputEventFunction = function() {
            var searchText = input.value.trim().toLowerCase();
            var keywords = searchText.split(/[\s\-]+/);
            if (keywords.length > 1) {
              keywords.push(searchText);
            }
            var resultItems = [];
            if (searchText.length > 0) {
              // perform local searching
              datas.forEach(function(data) {
                var isMatch = false;
                var hitCount = 0;
                var searchTextCount = 0;
                var title = data.title.trim();
                var titleInLowerCase = title.toLowerCase();
                var content = data.content.trim().replace(/<[^>]+>/g,"");
                var contentInLowerCase = content.toLowerCase();
                var articleUrl = decodeURIComponent(data.url);
                var indexOfTitle = [];
                var indexOfContent = [];
                // only match articles with not empty titles
                if(title != '') {
                  keywords.forEach(function(keyword) {
                    function getIndexByWord(word, text, caseSensitive) {
                      var wordLen = word.length;
                      if (wordLen === 0) {
                        return [];
                      }
                      var startPosition = 0, position = [], index = [];
                      if (!caseSensitive) {
                        text = text.toLowerCase();
                        word = word.toLowerCase();
                      }
                      while ((position = text.indexOf(word, startPosition)) > -1) {
                        index.push({position: position, word: word});
                        startPosition = position + wordLen;
                      }
                      return index;
                    }

                    indexOfTitle = indexOfTitle.concat(getIndexByWord(keyword, titleInLowerCase, false));
                    indexOfContent = indexOfContent.concat(getIndexByWord(keyword, contentInLowerCase, false));
                  });
                  if (indexOfTitle.length > 0 || indexOfContent.length > 0) {
                    isMatch = true;
                    hitCount = indexOfTitle.length + indexOfContent.length;
                  }
                }

                // show search results

                if (isMatch) {
                  // sort index by position of keyword

                  [indexOfTitle, indexOfContent].forEach(function (index) {
                    index.sort(function (itemLeft, itemRight) {
                      if (itemRight.position !== itemLeft.position) {
                        return itemRight.position - itemLeft.position;
                      } else {
                        return itemLeft.word.length - itemRight.word.length;
                      }
                    });
                  });

                  // merge hits into slices

                  function mergeIntoSlice(text, start, end, index) {
                    var item = index[index.length - 1];
                    var position = item.position;
                    var word = item.word;
                    var hits = [];
                    var searchTextCountInSlice = 0;
                    while (position + word.length <= end && index.length != 0) {
                      if (word === searchText) {
                        searchTextCountInSlice++;
                      }
                      hits.push({position: position, length: word.length});
                      var wordEnd = position + word.length;

                      // move to next position of hit

                      index.pop();
                      while (index.length != 0) {
                        item = index[index.length - 1];
                        position = item.position;
                        word = item.word;
                        if (wordEnd > position) {
                          index.pop();
                        } else {
                          break;
                        }
                      }
                    }
                    searchTextCount += searchTextCountInSlice;
                    return {
                      hits: hits,
                      start: start,
                      end: end,
                      searchTextCount: searchTextCountInSlice
                    };
                  }

                  var slicesOfTitle = [];
                  if (indexOfTitle.length != 0) {
                    slicesOfTitle.push(mergeIntoSlice(title, 0, title.length, indexOfTitle));
                  }

                  var slicesOfContent = [];
                  while (indexOfContent.length != 0) {
                    var item = indexOfContent[indexOfContent.length - 1];
                    var position = item.position;
                    var word = item.word;
                    // cut out 100 characters
                    var start = position - 20;
                    var end = position + 80;
                    if(start < 0){
                      start = 0;
                    }
                    if (end < position + word.length) {
                      end = position + word.length;
                    }
                    if(end > content.length){
                      end = content.length;
                    }
                    slicesOfContent.push(mergeIntoSlice(content, start, end, indexOfContent));
                  }

                  // sort slices in content by search text's count and hits' count

                  slicesOfContent.sort(function (sliceLeft, sliceRight) {
                    if (sliceLeft.searchTextCount !== sliceRight.searchTextCount) {
                      return sliceRight.searchTextCount - sliceLeft.searchTextCount;
                    } else if (sliceLeft.hits.length !== sliceRight.hits.length) {
                      return sliceRight.hits.length - sliceLeft.hits.length;
                    } else {
                      return sliceLeft.start - sliceRight.start;
                    }
                  });

                  // select top N slices in content

                  var upperBound = parseInt('1');
                  if (upperBound >= 0) {
                    slicesOfContent = slicesOfContent.slice(0, upperBound);
                  }

                  // highlight title and content

                  function highlightKeyword(text, slice) {
                    var result = '';
                    var prevEnd = slice.start;
                    slice.hits.forEach(function (hit) {
                      result += text.substring(prevEnd, hit.position);
                      var end = hit.position + hit.length;
                      result += '<b class="search-keyword">' + text.substring(hit.position, end) + '</b>';
                      prevEnd = end;
                    });
                    result += text.substring(prevEnd, slice.end);
                    return result;
                  }

                  var resultItem = '';

                  if (slicesOfTitle.length != 0) {
                    resultItem += "<li><a href='" + articleUrl + "' class='search-result-title'>" + highlightKeyword(title, slicesOfTitle[0]) + "</a>";
                  } else {
                    resultItem += "<li><a href='" + articleUrl + "' class='search-result-title'>" + title + "</a>";
                  }

                  slicesOfContent.forEach(function (slice) {
                    resultItem += "<a href='" + articleUrl + "'>" +
                      "<p class=\"search-result\">" + highlightKeyword(content, slice) +
                      "...</p>" + "</a>";
                  });

                  resultItem += "</li>";
                  resultItems.push({
                    item: resultItem,
                    searchTextCount: searchTextCount,
                    hitCount: hitCount,
                    id: resultItems.length
                  });
                }
              })
            };
            if (keywords.length === 1 && keywords[0] === "") {
              resultContent.innerHTML = '<div id="no-result"><i class="fa fa-search fa-5x" /></div>'
            } else if (resultItems.length === 0) {
              resultContent.innerHTML = '<div id="no-result"><i class="fa fa-frown-o fa-5x" /></div>'
            } else {
              resultItems.sort(function (resultLeft, resultRight) {
                if (resultLeft.searchTextCount !== resultRight.searchTextCount) {
                  return resultRight.searchTextCount - resultLeft.searchTextCount;
                } else if (resultLeft.hitCount !== resultRight.hitCount) {
                  return resultRight.hitCount - resultLeft.hitCount;
                } else {
                  return resultRight.id - resultLeft.id;
                }
              });
              var searchResultList = '<ul class=\"search-result-list\">';
              resultItems.forEach(function (result) {
                searchResultList += result.item;
              })
              searchResultList += "</ul>";
              resultContent.innerHTML = searchResultList;
            }
          }

          if ('auto' === 'auto') {
            input.addEventListener('input', inputEventFunction);
          } else {
            $('.search-icon').click(inputEventFunction);
            input.addEventListener('keypress', function (event) {
              if (event.keyCode === 13) {
                inputEventFunction();
              }
            });
          }

          // remove loading animation
          $(".local-search-pop-overlay").remove();
          $('body').css('overflow', '');

          proceedsearch();
        }
      });
    }

    // handle and trigger popup window;
    $('.popup-trigger').click(function(e) {
      e.stopPropagation();
      if (isfetched === false) {
        searchFunc(path, 'local-search-input', 'local-search-result');
      } else {
        proceedsearch();
      };
    });

    $('.popup-btn-close').click(onPopupClose);
    $('.popup').click(function(e){
      e.stopPropagation();
    });
    $(document).on('keyup', function (event) {
      var shouldDismissSearchPopup = event.which === 27 &&
        $('.search-popup').is(':visible');
      if (shouldDismissSearchPopup) {
        onPopupClose();
      }
    });
  </script>





  

  

  

  
  
  
  <link rel="stylesheet" href="/lib/needsharebutton/needsharebutton.css">

  
  
  <script src="/lib/needsharebutton/needsharebutton.js"></script>

  <script>
    
      pbOptions = {};
      
          pbOptions.iconStyle = "box";
      
          pbOptions.boxForm = "horizontal";
      
          pbOptions.position = "bottomCenter";
      
          pbOptions.networks = "Weibo,Wechat,Douban,QQZone,Twitter,Facebook";
      
      new needShareButton('#needsharebutton-postbottom', pbOptions);
    
    
      flOptions = {};
      
          flOptions.iconStyle = "box";
      
          flOptions.boxForm = "horizontal";
      
          flOptions.position = "middleRight";
      
          flOptions.networks = "Weibo,Wechat,Douban,QQZone,Twitter,Facebook";
      
      new needShareButton('#needsharebutton-float', flOptions);
    
  </script>

  

  

  

  

</body>
</html>
